#include "messenger.h"

#include <QTcpSocket>
#include <QCoreApplication>
#include <QProgressDialog>
#include <QDebug>


Messenger::Messenger(const QString &host, int port, QProgressDialog *progress) :
    QObject(),
    m_remoteHost(host),
    m_remotePort(port),    
    m_lastMessage(0),
    m_tmpFile(0),
    m_res(NoError),
    m_progress(progress)

{
    m_socket = new QTcpSocket();
    connect(m_socket, SIGNAL(readyRead()),this , SLOT(readyRead()));
    connect(m_socket, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(socketError(QAbstractSocket::SocketError)));
    if( m_progress != 0 )
        connect(m_progress, SIGNAL(canceled()), this, SLOT(cancel()));       
    m_messageEndBuff.reserve(strlen(BODYEND)*2);
}


Messenger::~Messenger()
{
    delete m_socket;
    m_socket = 0;
    if( m_lastMessage != 0 )
        delete m_lastMessage;
    if(m_tmpFile && m_tmpFile->fileName().size()>0) {
        m_tmpFile->remove();
        delete m_tmpFile;
    }
}

Messenger::MessengerError Messenger::sendMessage(Message *msg)
{
    bool res;
    m_readSize = 0;
    m_totalSize = 0;
    m_res = NoError;

    if(m_progress) {
        m_progress->setLabelText("Отправка запроса");
        connect(m_progress, SIGNAL(canceled()), this , SLOT(cancel()));
    }

    if(m_lastMessage != 0) {
        delete m_lastMessage;
        m_lastMessage = 0;
    }
    if(m_tmpFile) {
        m_tmpFile->remove();
        delete m_tmpFile;
    }

    m_tmpFile = new QTemporaryFile();
    m_tmpFile->setAutoRemove(false);
    m_tmpFile->open();

    m_socket->connectToHost(m_remoteHost,m_remotePort);
    res = m_socket->waitForConnected(15000);

    int msgLength = msg->getMessageLength();
    int sent = 0;
    if(res) {
        QTemporaryFile *file = msg->getBodyFile();
        if(file->isOpen())
            file->reset();
        else
            file->open();

        if( msg->getParam("ZIP").toInt() == 2 ) {
            quint32 size = msg->getMessageLength()+7;msgLength+=7;
            char binSize[7] = {'B','I','N',0,0,0,0};
            memcpy(&binSize[3], &size, sizeof(quint32));
            sent += m_socket->write(binSize,7);
        }
        for (QMap<QString, QString>::const_iterator i = msg->getHeadBegin(); i != msg->getHeadEnd(); ++i) {
            sent += m_socket->write(i.key().toAscii());
            sent += m_socket->write("=");
            sent += m_socket->write(i.value().toAscii());
            sent += m_socket->write(";");
        }

        sent += m_socket->write(HEADEND);

        while(!file->atEnd()) {
            QByteArray ba = file->readLine();
            sent += m_socket->write(ba);
        }

        sent += m_socket->write(BODYEND);
        res = m_socket->waitForBytesWritten();
        qDebug()<<"MsgLength:"<<msgLength<<" SentBytes:"<<sent;
        while( m_socket->isOpen() && m_res == NoError ) {
            QCoreApplication::processEvents(QEventLoop::AllEvents, 80);
        }
    } else
        m_res = NoConnection;

    return m_res;
}

Messenger::MessengerError Messenger::sendMessage(Message *message, const QString &host, int port, QProgressDialog *progress)
{
    m_remoteHost = host;
    m_remotePort = port;
    m_progress = progress;
    return sendMessage(message);
}

void Messenger::readyRead()
{
    if(m_progress) {
        m_progress->setLabelText("Получение данных");
    }
    QByteArray ba = m_socket->readAll();

    if( m_readSize == 0 ) {
        int pos1 = ba.indexOf("SIZE");
        if(pos1>0) {
            pos1 += 5;
            int pos2 = ba.indexOf(';',pos1);
            if( pos2 > 0 ) {
                QString total = ba.mid(pos1,pos2-pos1);
                m_totalSize = total.toInt();
                if(m_progress)
                    m_progress->setRange(0, m_totalSize);
            }
        }
    }

    m_readSize += ba.size();

    if(m_progress && m_totalSize > 0) {
        m_progress->setValue(m_readSize);
        QCoreApplication::processEvents(QEventLoop::ExcludeSocketNotifiers,80);
    }

    m_messageEndBuff = m_prevChunkEnd;
    m_prevChunkEnd = ba.right(strlen(BODYEND));
    m_messageEndBuff.append(m_prevChunkEnd);
    m_tmpFile->write(ba);

    if( m_messageEndBuff.endsWith(BODYEND) ) {
        qDebug()<<"EndMessage"<<m_tmpFile->fileName()<< " Size:" << m_readSize;
        m_lastMessage = new Message(m_tmpFile);
        m_socket->close();        
    }
}

void Messenger::socketError(QAbstractSocket::SocketError socketError)
{    
    qDebug()<< "SocketError: "<< socketError ;
    m_res = ConnectionLost;
    if(m_socket != 0)
        m_socket->close();
}

void Messenger::cancel()
{    
    qDebug()<<"Cancel socket";
    disconnect(m_progress, SIGNAL(canceled()), this , SLOT(cancel()));
    m_res = TransmissionCanceled;
    if(m_socket != 0)
        m_socket->close();
}
